// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.core.utils;

public class HashMap {
    private int capacity = 2;
    private int elements = 0;
    private HashMap.Bucket[] buckets = new HashMap.Bucket[this.capacity];

    public HashMap() {
        for (int _int = 0; _int < this.capacity; _int++) {
            this.buckets[_int] = new HashMap.Bucket();
        }
    }

    public void clear() {
        this.elements = 0;

        for (int _int = 0; _int < this.capacity; _int++) {
            this.buckets[_int].clear();
        }
    }

    private void grow() {
        HashMap.Bucket[] bucket0 = this.buckets;
        this.capacity *= 2;
        this.elements = 0;
        this.buckets = new HashMap.Bucket[this.capacity];

        for (int int0 = 0; int0 < this.capacity; int0++) {
            this.buckets[int0] = new HashMap.Bucket();
        }

        for (int int1 = 0; int1 < bucket0.length; int1++) {
            HashMap.Bucket bucket1 = bucket0[int1];

            for (int int2 = 0; int2 < bucket1.size(); int2++) {
                if (bucket1.keys[int2] != null) {
                    this.put(bucket1.keys[int2], bucket1.values[int2]);
                }
            }
        }
    }

    public Object get(Object key) {
        HashMap.Bucket bucket = this.buckets[Math.abs(key.hashCode()) % this.capacity];

        for (int _int = 0; _int < bucket.size(); _int++) {
            if (bucket.keys[_int] != null && bucket.keys[_int].equals(key)) {
                return bucket.values[_int];
            }
        }

        return null;
    }

    public Object remove(Object key) {
        HashMap.Bucket bucket = this.buckets[Math.abs(key.hashCode()) % this.capacity];
        Object object = bucket.remove(key);
        if (object != null) {
            this.elements--;
            return object;
        } else {
            return null;
        }
    }

    public Object put(Object key, Object value) {
        if (this.elements + 1 >= this.buckets.length) {
            this.grow();
        }

        Object object = this.remove(key);
        HashMap.Bucket bucket = this.buckets[Math.abs(key.hashCode()) % this.capacity];
        bucket.put(key, value);
        this.elements++;
        return object;
    }

    public int size() {
        return this.elements;
    }

    public boolean isEmpty() {
        return this.size() == 0;
    }

    public HashMap.Iterator iterator() {
        return new HashMap.Iterator(this);
    }

    public String toString() {
        Object object = new String();

        for (int int0 = 0; int0 < this.buckets.length; int0++) {
            HashMap.Bucket bucket = this.buckets[int0];

            for (int int1 = 0; int1 < bucket.size(); int1++) {
                if (bucket.keys[int1] != null) {
                    if (object.length() > 0) {
                        object = object + ", ";
                    }

                    object = object + bucket.keys[int1] + "=" + bucket.values[int1];
                }
            }
        }

        return "HashMap[" + object + "]";
    }

    private static class Bucket {
        public Object[] keys;
        public Object[] values;
        public int count;
        public int nextIndex;

        public void put(Object object0, Object object1) throws IllegalStateException {
            if (this.keys == null) {
                this.grow();
                this.keys[0] = object0;
                this.values[0] = object1;
                this.nextIndex = 1;
                this.count = 1;
            } else {
                if (this.count == this.keys.length) {
                    this.grow();
                }

                for (int _int = 0; _int < this.keys.length; _int++) {
                    if (this.keys[_int] == null) {
                        this.keys[_int] = object0;
                        this.values[_int] = object1;
                        this.count++;
                        this.nextIndex = Math.max(this.nextIndex, _int + 1);
                        return;
                    }
                }

                throw new IllegalStateException("bucket is full");
            }
        }

        public Object remove(Object object0) {
            for (int _int = 0; _int < this.nextIndex; _int++) {
                if (this.keys[_int] != null && this.keys[_int].equals(object0)) {
                    Object object1 = this.values[_int];
                    this.keys[_int] = null;
                    this.values[_int] = null;
                    this.count--;
                    return object1;
                }
            }

            return null;
        }

        private void grow() {
            if (this.keys == null) {
                this.keys = new Object[2];
                this.values = new Object[2];
            } else {
                Object[] object0 = this.keys;
                Object[] object1 = this.values;
                this.keys = new Object[object0.length * 2];
                this.values = new Object[object1.length * 2];
                System.arraycopy(object0, 0, this.keys, 0, object0.length);
                System.arraycopy(object1, 0, this.values, 0, object1.length);
            }
        }

        public int size() {
            return this.nextIndex;
        }

        public void clear() {
            for (int _int = 0; _int < this.nextIndex; _int++) {
                this.keys[_int] = null;
                this.values[_int] = null;
            }

            this.count = 0;
            this.nextIndex = 0;
        }
    }

    public static class Iterator {
        private HashMap hashMap;
        private int bucketIdx;
        private int keyValuePairIdx;
        private int elementIdx;
        private Object currentKey;
        private Object currentValue;

        public Iterator(HashMap hashmap) {
            this.hashMap = hashmap;
            this.reset();
        }

        public HashMap.Iterator reset() {
            this.bucketIdx = 0;
            this.keyValuePairIdx = 0;
            this.elementIdx = 0;
            this.currentKey = null;
            this.currentValue = null;
            return this;
        }

        public boolean hasNext() {
            return this.elementIdx < this.hashMap.elements;
        }

        public boolean advance() {
            while (this.bucketIdx < this.hashMap.buckets.length) {
                HashMap.Bucket bucket = this.hashMap.buckets[this.bucketIdx];
                if (this.keyValuePairIdx == bucket.size()) {
                    this.keyValuePairIdx = 0;
                    this.bucketIdx++;
                } else {
                    while (this.keyValuePairIdx < bucket.size()) {
                        if (bucket.keys[this.keyValuePairIdx] != null) {
                            this.currentKey = bucket.keys[this.keyValuePairIdx];
                            this.currentValue = bucket.values[this.keyValuePairIdx];
                            this.keyValuePairIdx++;
                            this.elementIdx++;
                            return true;
                        }

                        this.keyValuePairIdx++;
                    }

                    this.keyValuePairIdx = 0;
                    this.bucketIdx++;
                }
            }

            return false;
        }

        public Object getKey() {
            return this.currentKey;
        }

        public Object getValue() {
            return this.currentValue;
        }
    }
}
